package com.yjtc.cbg.imageloader.util;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.LruCache;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;

import java.util.LinkedList;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * Created by chenboge on 16/7/3.
 */
public class ImageLoader {

    //图片缓存存储容器
    private LruCache<String, Bitmap> mLruCache;


    //线程池，用语从网络获取图片啊对象
    private ExecutorService mLocalThread;

    //添加信号量，防止在使用对象时还没创建对象实例
    private Semaphore mPoolThreadHandlersemaphore=new Semaphore(0);
    //添加信号量，向线程池添加任务，当线程池线程使用完后，等待
    private Semaphore mLocalThreadsemaphore;

    //默认线程个数
    private static final int DEFAULT_THREAD_COUNT = 5;

    //设置图片管理容器对图片管理的方式,FIFO,LIFO

    private Type mType = Type.FIFO;

    public enum Type {
        FIFO, LIFO;
    }

    //任务列表，用于从网络获取数据
    private LinkedList<Runnable> mTaskQueue;

    //后台轮询线程,采用handler＋looper＋thread的方式
    private Thread mPoolThread;
    private Handler mPoolThreadHandler;

    //ui线程的handler
    private Handler UIHandler;

    private static ImageLoader mInstance;

    public ImageLoader(int ThreadCount, Type mType) {
        init(ThreadCount, mType);
    }

    private void init(int threadCount, final Type mType) {
        mPoolThread = new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                mPoolThreadHandler = new Handler() {
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        //对消息进行处理
                        mLocalThread.execute(getTask());
                        try {
                            mLocalThreadsemaphore.acquire();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                };
                mPoolThreadHandlersemaphore.release();
                Looper.loop();
            }
        });
        mPoolThread.start();

        mLocalThreadsemaphore = new Semaphore(threadCount);

        //获取应用最大可用内存
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        //设置缓存占用内存
        int cache = maxMemory / 8;

        //初始化lrucache内存管理缓存
        mLruCache = new LruCache<String, Bitmap>(cache) {
            //计算每一张图片占用内存大小
            @Override
            protected int sizeOf(String key, Bitmap value) {
                //每一行占用的字节数和行高的乘积
                return value.getRowBytes() * value.getHeight();
            }
        };

        //初始化线程池
        mLocalThread = Executors.newFixedThreadPool(threadCount);
        //初始化任务 队列
        mTaskQueue = new LinkedList<Runnable>();

        this.mType = mType;
    }

    private Runnable getTask() {
        if(mType==Type.FIFO){
            return mTaskQueue.removeFirst();
        }else {
            return mTaskQueue.removeLast();
        }
    }

    //单例模式，防止创建多个对象
    public static ImageLoader getmInstance() {
        if (null == mInstance) {
            synchronized (ImageLoader.class) {
                if (null == mInstance) {
                    mInstance = new ImageLoader(DEFAULT_THREAD_COUNT, Type.LIFO);
                }
            }
        }
        return mInstance;
    }

    //为imageview设置图片
    private void LoadImage(final String path, final ImageView imageView){
        imageView.setTag(path);
        if(UIHandler==null){
            UIHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    //设置图片,加载图片时可能存在异步加载，获取到这个message时可能不是这个imageview了，所以需要将imageview和bitmap，path封装在一起
                    //也可能复用imageview的时候，应该加载新的path地址的图片
                    ImgBeanHolder holder = (ImgBeanHolder) msg.obj;
                    ImageView imageView1 = holder.imageView;
                    String mpath = holder.path;
                    Bitmap bitmap = holder.bitmap;
                    if(imageView1.getTag().toString().equals(mpath)){
                        imageView1.setImageBitmap(bitmap);
                    }
                }
            };
        }

        //获取图片时分三级，先从缓存获取，再从内存获取，最后网络加载
        final Bitmap bitmap=getBitmapFromLruCache(path);
        if(null!=bitmap){
        notifyBitmapChange(imageView,bitmap,path);
        }else {
           addTask(new Runnable(){
               @Override
               public void run() {
                   //从网络获取图片的方法代码,
                   //加载图片
                   //图片压缩

                   //获取图片需要压缩的大小
                ImageSize imageSize=getImageSize(imageView);
                 Bitmap bitmap1=decodeSampleBitmapFromPath(path,imageSize.imageHeight,imageSize.imageWidth);
                   addBitmapToLrucache(path,bitmap1);
                   notifyBitmapChange(imageView,bitmap1,path);
                   mLocalThreadsemaphore.release();
               }
           });
        }
    }

    private void addBitmapToLrucache(String path, Bitmap bitmap1) {
        if(getBitmapFromLruCache(path)==null){
            if(bitmap1!=null){
                mLruCache.put(path, bitmap1);
            }
        }
    }

    //通知ui更新视图，图片获取完成
    private void notifyBitmapChange(ImageView imageView,Bitmap bitmap,String path){
        Message message = Message.obtain();
        ImgBeanHolder holder = new ImgBeanHolder();
        holder.imageView = imageView;
        holder.bitmap = bitmap;
        holder.path = path;
        message.obj = holder;
        UIHandler.sendMessage(message);
    }

    private Bitmap decodeSampleBitmapFromPath(String path, int reqHeight, int reqWidth) {
        //获取原始图片
        BitmapFactory.Options options = new BitmapFactory.Options();
        //不把图片加载到内存，获取图片的宽高尺寸
        options.inJustDecodeBounds = true;
        //把尺寸放入option中
        BitmapFactory.decodeFile(path, options);
        int injustSimpleSize=getSimpleSize(options,reqHeight,reqWidth);

        options.inJustDecodeBounds = false;
        Bitmap bitmap1 = BitmapFactory.decodeFile(path, options);
        return bitmap1;
    }

    private int getSimpleSize(BitmapFactory.Options options, int reqHeight, int reqWidth) {
        int simpleSize=1;
        int actualHeight = options.outHeight;
        int actualWidth = options.outWidth;

        if(actualHeight>reqHeight||actualWidth>reqWidth){
            int widthRadio =Math.round( actualWidth * 1.0f / reqWidth);
            int heightRadio =Math.round( actualHeight * 1.0f / reqHeight);
            simpleSize = Math.max(widthRadio, heightRadio);
        }
        return simpleSize;
    }

    private ImageSize getImageSize(ImageView imageView) {
        ImageSize size = new ImageSize();

        DisplayMetrics displayMetrics = imageView.getContext().getResources().getDisplayMetrics();
        ViewGroup.LayoutParams layoutParams = imageView.getLayoutParams();
        int width=imageView.getWidth();//获取imageview实际的的宽高
        if(width<=0){
            //获取设置在lp中的宽度，在layout中设置的宽度
            width = layoutParams.width;
        }

        if(width<=0){
            width = imageView.getMaxWidth();//imageview可能设置为wrap_content，获取图片最大宽度
        }

        if(width<=0){
            width = displayMetrics.widthPixels;//屏幕的宽度
        }


        int height=imageView.getHeight();//获取imageview实际的的宽高
        if(height<=0){
            //获取设置在lp中的宽度，在layout中设置的宽度
            height = layoutParams.height;
        }

        if(width<=0){
            height = imageView.getMaxHeight();//imageview可能设置为wrap_content,match_parent,fill_parent，仍然是小雨0的，获取图片最大宽度
        }

        if(width<=0){
            height = displayMetrics.heightPixels;//屏幕的宽度
        }

        size.imageWidth = width;
        size.imageHeight = height;
        return size;
    }

    private synchronized void addTask(Runnable runnable) {
        mTaskQueue.add(runnable);
        try {
            if(mPoolThreadHandler==null){
                mPoolThreadHandlersemaphore.acquire();
            }
            mPoolThreadHandler.sendEmptyMessage(0x110);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //从缓存获取图片
    private Bitmap getBitmapFromLruCache(String path) {
        return mLruCache.get(path);
    }


    //创建holder的目的，是为了更好的将imageview和bitmap进行封装
    public class ImgBeanHolder{
        ImageView imageView;
        String path;
        Bitmap bitmap;
    }

    //图片压缩后的图片尺寸的封装
    public class ImageSize{
      int imageWidth;
      int imageHeight;
    }
}
